home *** CD-ROM | disk | FTP | other *** search
- /* des.c -- this file contains an optimized C-based DES algorithm */
- /* implementation. Many loops are stretched out into straight-line code, */
- /* so this version is not particularly short, modular, or readable. (size */
- /* as of 31 Aug 83: 7338+1426+6372 = 15136b = 035440b) However, it is */
- /* quick. (A DES encryption times at approximately 7 user ms on a C/70) It */
- /* reads its key schedule and certain tables from files generated by */
- /* associated programs ksb.c and tblbld.c. John Linn -- 8 April 1983 */
- /* "Bug" fix 17 Feb 1984 - insert masking so as to have E work on
- 32 bit machines with sign extension on right shifts (like Vax, 68k (?)) */
- /* observation: when compiled onto vax, takes only ~ 2.6 ms to encrypt */
-
- #include <stdio.h>
- #define LMASK 0XFCFCFCFCL;
-
- /* data structures to be read from files */
- static long ip [2] [256];
- static long ipi [2] [256];
- static long snop [8] [64];
- unsigned ks [16] [4];
-
- /* rdfiles -- reads filed info, returns 1 iff success, 0 otherwise */
- int rdfiles ()
- {
- int i, j;
- FILE *fp, *fopen ();
-
- if (NULL == (fp = fopen ("ip", "r")))
- {
- printf ("des -- can't read file 'ip'\n");
- return (0);
- }
- for (i = 0; i < 2; i++)
- for (j = 0; j < 256; j++)
- if (EOF == fscanf (fp, "%lx", &ip [i] [j]))
- {
- printf ("des -- 'ip' read failed at i=%d, j=%d\n", i, j);
- return (0);
- }
- fclose (fp);
-
- if (NULL == (fp = fopen ("ipi", "r")))
- {
- printf ("des -- can't read file 'ipi'\n");
- return (0);
- }
- for (i = 0; i < 2; i++)
- for (j = 0; j < 256; j++)
- if (EOF == fscanf (fp, "%lx", &ipi [i] [j]))
- {
- printf ("des -- 'ipi' read failed at i=%d, j=%d\n", i, j);
- return (0);
- }
- fclose (fp);
-
- if (NULL == (fp = fopen ("snop", "r")))
- {
- printf ("des -- can't read file 'snop'\n");
- return (0);
- }
- for (i = 0; i < 8; i++)
- for (j = 0; j < 64; j++)
- if (EOF == fscanf (fp, "%lx", &snop [i] [j]))
- {
- printf ("des -- 'snop' read failed at i=%d, j=%d\n", i, j);
- return (0);
- }
- fclose (fp);
-
- if (NULL == (fp = fopen ("ks", "r")))
- {
- printf ("des -- can't read file 'ks'\n");
- return (0);
- }
- for (i = 0; i < 16; i++)
- for (j = 0; j < 4; j++)
- if (EOF == fscanf (fp, "%x", &ks [i] [j]))
- {
- printf ("des -- 'ks' read failed at i=%d, j=%d\n", i, j);
- return (0);
- }
- fclose (fp);
-
- return (1); /* success */
- }
-
- #define BINBLK 8 /* number of bytes in an encryption chunk */
- #define BINLNG 4 /* the number of bytes in 32 bits of a long */
-
- /* doip -- use ip table to permute 64 bits from inar to outar */
- doip (inar, outar)
- long inar [2];
- long outar [2];
- {
- extern long ip [2] [256];
-
- outar [0] = outar [1] = 0L;
-
- outar [0] |= ip [0] [0XFF & inar [1]];
- outar [1] |= ip [1] [0XFF & inar [1]];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ip [0] [0XFF & (inar [1] >> 8)];
- outar [1] |= ip [1] [0XFF & (inar [1] >> 8)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ip [0] [0XFF & (inar [1] >> 16)];
- outar [1] |= ip [1] [0XFF & (inar [1] >> 16)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ip [0] [0XFF & (inar [1] >> 24)];
- outar [1] |= ip [1] [0XFF & (inar [1] >> 24)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ip [0] [0XFF & inar [0]];
- outar [1] |= ip [1] [0XFF & inar [0]];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ip [0] [0XFF & (inar [0] >> 8)];
- outar [1] |= ip [1] [0XFF & (inar [0] >> 8)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ip [0] [0XFF & (inar [0] >> 16)];
- outar [1] |= ip [1] [0XFF & (inar [0] >> 16)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ip [0] [0XFF & (inar [0] >> 24)];
- outar [1] |= ip [1] [0XFF & (inar [0] >> 24)];
- }
-
- /* doipi -- use ipi to perform ip-inverse */
- /* doesn't use ipis table: knowledge of byte order is hardcoded */
- doipi (inar, outar)
- long inar [2];
- long outar [2];
- {
- extern long ipi [2] [256];
-
- outar [0] = outar [1] = 0L;
-
- outar [0] |= ipi [0] [0XFF & (inar [1] >> 24)]; /* "5" */
- outar [1] |= ipi [1] [0XFF & (inar [1] >> 24)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ipi [0] [0XFF & (inar [0] >> 24)]; /* "1" */
- outar [1] |= ipi [1] [0XFF & (inar [0] >> 24)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ipi [0] [0XFF & (inar [1] >> 16)]; /* "6" */
- outar [1] |= ipi [1] [0XFF & (inar [1] >> 16)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ipi [0] [0XFF & (inar [0] >> 16)]; /* "2" */
- outar [1] |= ipi [1] [0XFF & (inar [0] >> 16)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ipi [0] [0XFF & (inar [1] >> 8)]; /* "7" */
- outar [1] |= ipi [1] [0XFF & (inar [1] >> 8)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ipi [0] [0XFF & (inar [0] >> 8)]; /* "3" */
- outar [1] |= ipi [1] [0XFF & (inar [0] >> 8)];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ipi [0] [0XFF & inar [1]]; /* "8" */
- outar [1] |= ipi [1] [0XFF & inar [1]];
- outar [0] <<= 1;
- outar [1] <<= 1;
- outar [0] |= ipi [0] [0XFF & inar [0]]; /* "4" */
- outar [1] |= ipi [1] [0XFF & inar [0]];
- }
-
- /* des_encrypt -- encrypt a block under key sched in ks */
- des_encrypt (inar, outar)
- long inar [2];
- long outar [2];
- {
- extern unsigned ks [16] [4];
- extern long snop [8] [64];
-
- register int round, oddbit;
- unsigned expan [4]; /* receives output of E transform */
- long sbout, scopy, tlong;
- long oarr [2];
-
- doip (inar, outar);
-
- for (round = 0; round < 16; round++)
- {
- sbout = 0L;
-
- tlong = outar [1];
- oddbit = (int) (01 & tlong);
- tlong >>= 1;
- tlong &= 0X7FFFFFFFL; /* defeat sign extend -- jl 17 feb 84 */
- if (oddbit) tlong |= 0X80000000L;
-
- tlong &= LMASK;
- expan [0] = (unsigned) (tlong >> 16);
- expan [1] = (unsigned) tlong;
-
- tlong = outar [1];
- oddbit = !! (tlong & 0X80000000L);
- tlong <<= 3;
- if (oddbit) tlong |= 04;
- tlong &= LMASK;
- expan [2] = (unsigned) (tlong >> 16);
- expan [3] = (unsigned) tlong;
-
- /* this code bypasses the alternative of loop setup
- and resultant computation within the loop for speed */
- expan [0] ^= ks [round] [0];
- sbout |= snop [0] [0X3F & (expan [0] >> 10)];
- sbout |= snop [1] [0X3F & (expan [0] >> 2)];
- expan [1] ^= ks [round] [1];
- sbout |= snop [2] [0X3F & (expan [1] >> 10)];
- sbout |= snop [3] [0X3F & (expan [1] >> 2)];
- expan [2] ^= ks [round] [2];
- sbout |= snop [4] [0X3F & (expan [2] >> 10)];
- sbout |= snop [5] [0X3F & (expan [2] >> 2)];
- expan [3] ^= ks [round] [3];
- sbout |= snop [6] [0X3F & (expan [3] >> 10)];
- sbout |= snop [7] [0X3F & (expan [3] >> 2)];
-
- scopy = outar [0];
- outar [0] = outar [1];
- outar [1] = scopy ^ sbout;
- }
-
- /* a final swap */
- scopy = outar [0];
- outar [0] = outar [1];
- outar [1] = scopy;
-
- doipi (outar, oarr); /* perform ip-inverse into temp copy */
- outar [0] = oarr [0];
- outar [1] = oarr [1];
- }
-
- /* des_decrypt -- decrypt a block under key sched in ks */
- des_decrypt (inar, outar)
- long inar [2];
- long outar [2];
- {
- extern unsigned ks [16] [4];
- extern long snop [8] [64];
-
- register int round, oddbit;
- unsigned expan [4]; /* receives output of E transform */
- long sbout, scopy, tlong;
- long oarr [2];
-
- doip (inar, outar);
-
- for (round = 15; round >= 0; round--)
- /* note that decryption selects schedule keys in opposite order */
- {
- sbout = 0L;
-
- tlong = outar [1];
- oddbit = (int) (01 & tlong);
- tlong >>= 1;
- tlong &= 0X7FFFFFFFL; /* defeat sign extend -- jl 17 feb 84 */
- if (oddbit) tlong |= 0X80000000L;
-
- tlong &= LMASK;
- expan [0] = (unsigned) (tlong >> 16);
- expan [1] = (unsigned) tlong;
-
- tlong = outar [1];
- oddbit = !! (tlong & 0X80000000L);
- tlong <<= 3;
- if (oddbit) tlong |= 04;
- tlong &= LMASK;
- expan [2] = (unsigned) (tlong >> 16);
- expan [3] = (unsigned) tlong;
-
- /* this code bypasses the alternative of loop setup
- and resultant computation within the loop for speed */
- expan [0] ^= ks [round] [0];
- sbout |= snop [0] [0X3F & (expan [0] >> 10)];
- sbout |= snop [1] [0X3F & (expan [0] >> 2)];
- expan [1] ^= ks [round] [1];
- sbout |= snop [2] [0X3F & (expan [1] >> 10)];
- sbout |= snop [3] [0X3F & (expan [1] >> 2)];
- expan [2] ^= ks [round] [2];
- sbout |= snop [4] [0X3F & (expan [2] >> 10)];
- sbout |= snop [5] [0X3F & (expan [2] >> 2)];
- expan [3] ^= ks [round] [3];
- sbout |= snop [6] [0X3F & (expan [3] >> 10)];
- sbout |= snop [7] [0X3F & (expan [3] >> 2)];
-
- scopy = outar [0];
- outar [0] = outar [1];
- outar [1] = scopy ^ sbout;
- }
-
- /* a final swap */
- scopy = outar [0];
- outar [0] = outar [1];
- outar [1] = scopy;
-
- doipi (outar, oarr); /* perform ip-inverse into temp copy */
- outar [0] = oarr [0];
- outar [1] = oarr [1];
- }
-
- /* facilities for timing */
- struct tbuffer
- {
- long proc_utime;
- long proc_stime;
- long child_utime;
- long child_stime;
- };
- struct tbuffer t_before;
- struct tbuffer t_after;
-
- main ()
- {
- int itnum, i;
- long plain [2], crypt [2], cprbuf [2];
- long udiff, bitsdone, u_msec;
-
- /* begin by reading tables and key schedule from files */
- printf ("Reading filed tables and key schedule...\n");
- if (1 != rdfiles ())
- {
- printf ("des -- couldn't get tables or key schedule\n");
- exit (1);
- }
-
- printf ("Enter input to encrypt as two hex longs: ");
- scanf ("%lx %lx", &plain [0], &plain [1]);
- des_encrypt (plain, crypt);
- printf ("Result of encryption: %lx %lx\n", crypt [0], crypt [1]);
-
- printf ("Enter number of test iterations [decimal]: ");
- scanf ("%d", &itnum);
-
- times (&t_before);
- for (i = 0; i < itnum; i++)
- {
- des_encrypt (plain, crypt);
- des_decrypt (crypt, cprbuf);
- if ((plain [0] != cprbuf [0]) || (plain [1] != cprbuf [1]))
- {
- printf ("Encrypt and decrypt disagree -- aborting!!\n");
- exit (1);
- }
- }
- times (&t_after);
- printf ("All encryptions and decryptions verified consistent\n");
-
- /* note: the following code won't work if one times a number
- of encryptions that take less than one tick, as can occur
- on a vax with a small number of tests */
- udiff = t_after.proc_utime - t_before.proc_utime;
- printf ("user 1/60 sec ticks = %ld\n", udiff);
- bitsdone = 2 * (itnum * 64);
- u_msec = (udiff * 1000) / 60;
- printf ("%ld user msec/DES cycle\n", u_msec / ((long) 2 * itnum));
- printf ("%ld bits/user second\n", (bitsdone * 1000) / u_msec);
- }
-
-